#include<iostream>
#include<fstream>
#include<string>
#include<vector>
#include<boost/filesystem.hpp>
#include"util.hpp"

#define SEP '\3'

using std::cout;
using std::endl;
using std::cerr;
using std::vector; 
using std::string; 

static const string origin_path="./data/html";//未去标签的路径
static const string goal_path="./data/goal_html";//去标签后的路径

struct DocInfo
{
    string title;//标题
    string content;//内容
    string url;//路径
};

bool EnumFiles(vector<string>& files_lists,const string& src_path);
bool ParserHtml(vector<string>& files_lists,vector<DocInfo>& goal_lists);
bool SaveHtml(const vector<DocInfo>& goal_lists,const string& des_path);

int main()
{
    //1.将html文档中的所有.html文件的路径全都放在files_lists中
    vector<string> files_lists;
    if(EnumFiles(files_lists,origin_path)==0)
    {
        cout<<"EnumFiles fail..."<<endl;
        return 1;
    }
    //2.对所有文件的内容进行“去标签化处理”，并进行解析
    vector<DocInfo> goal_lists;
    if(ParserHtml(files_lists,goal_lists)==0)
    {
        cout<<"ParserHtml fail..."<<endl;
        return 2;
    }
    //3.把解析完毕的各个文件的内容，写入到goal_path文件中，并按'\3'作为每个文档的分隔符
    if(SaveHtml(goal_lists,goal_path)==0)
    {
        cout<<"SaveHtml fail..."<<endl;
        return 3;
    }

    return 0;
}

bool EnumFiles(vector<string>& files_lists,const string& src_path)
{
    namespace fs=boost::filesystem; //给boost::filesystem换个名字fs
    fs::path root_path(src_path);//根路径

    if(fs::exists(root_path)==0)//判断路径是否正确/存在
    {
        cerr<<"not exists..."<<endl;
        return false;
    }
    //int count=0;
    fs::recursive_directory_iterator end;//定义一个空的迭代器，用来表示索引的尾巴

    int cnt=0;
    for(fs::recursive_directory_iterator it(root_path);it!=end;it++)
    {
        if(fs::is_regular_file(*it)==0)continue;//过滤掉非常规文件，如目录
        if(it->path().extension()!=".html")continue;//过滤掉后缀不是.html的文件
        //cout<<++count<<",debug: "<<it->path().string()<<endl;
        files_lists.push_back(it->path().string());//it是迭代器，it->path()是一个path类对象，it->path().string()是一个字符串

        //cout<<"正在将第"<<++cnt<<"个文档的名字写入vector..."<<endl;
    }

    return true; 
}

static bool ParseTitle(const string& result,string& dest)
{
    size_t begin=result.find("<title>");
    if(begin==string::npos)return false;

    size_t end=result.find("</title>");
    if(end==string::npos)return false;

    if(begin>=end)return false;

    begin+=string("<title>").size();
    dest=result.substr(begin,end-begin);

    return true;
}
static bool ParseContent(const string& result,string& dest)
{
    enum status{LABEL,CONTENT};//定义一个状态机

    status s=LABEL;

    for(auto c:result)
    {
        switch(s)
        {
            case LABEL:
                if(c=='>')s=CONTENT;//表示一个标签的结束
            break;
            case CONTENT:
                if(c=='<')s=LABEL;//表示一个新标签的开始
                else 
                {
                    if(c=='\n')
                    {
                        c=' ';
                    }
                    dest+=c; //真正的content
                }
            break;
            default:
                break;
        }
    }

    return true;
}
static bool ParseUrl(const string& file_path,string& dest)
{
    static string url_head="https://www.boost.org/doc/libs/1_84_0/doc/html";
    string url_tail=file_path.substr(origin_path.size());//例如：./data/html/array.html  ret_value=/array.html

    dest=url_head+url_tail;
    return true;
}

void ShowDebug(DocInfo& doc)
{
    static int n=0;
    
    if(n<1)
    {
        cout<<"title:"<<doc.title<<endl;
        cout<<"content:"<<doc.content<<endl;
        cout<<"url:"<<doc.url<<endl;
        n++;
    }
}

bool ParserHtml(vector<string>& files_lists,vector<DocInfo>& goal_lists)
{
    int cnt=0;
    for(auto& file_path:files_lists)
    {
        //1.读取文件内容，并将其存放在一个字符串中
        string result;
        if(0==ns_util::FileUtil::ReadFile(file_path,result))continue;//读取失败，就跳过后面的内容，开始读下一个
        DocInfo doc;
        //2.解析目标文件，提取title字段
        if(0==ParseTitle(result,doc.title))continue;
        //3.解析目标文件，提取content字段
        if(0==ParseContent(result,doc.content))continue;
        //4.解析目标文件，提取url
        if(0==ParseUrl(file_path,doc.url))continue;

        //done,来到这里，说明doc的字段都已经被成功填充了
        goal_lists.push_back(std::move(doc));//这里是拷贝，代价较大，可以优化

        //cout<<"正在将第"<<++cnt<<"个文档去标签后的结果写入vector..."<<endl;
        //break;

        //for debug
        //ShowDebug(doc);
    }
    return true; 
}
bool SaveHtml(const vector<DocInfo>& goal_lists,const string& dest_path)
{
    //函数功能：将goal_lists中的所有内容，以字符串的类型，写入路径为des_path的文件中
    std::ofstream ofs(dest_path,std::ios_base::out | std::ios_base::binary);
    if(ofs.is_open()==0)
    {
        cout<<"dest_path open fail..."<<endl;
        return false;
    }

    int cnt=0;
    for(auto& file:goal_lists)
    {
        //将file中的title、content、url拼接到一起，并用'\3'分隔开来
        string result=file.title;
        result+=SEP;
        result+=file.content;
        result+=SEP;
        result+=file.url;
        result+='\n';
        //将一个完整的文档写入ofs中
        ofs.write(result.c_str(),result.size());

        cout<<"正在将第"<<++cnt<<"个文档写入goal_html..."<<endl;
    }

    return true;
}



















